www.gusucode.com > VC 编写的VC++工程清理工具-源码程序 > VC 编写的VC++工程清理工具-源码程序/code/CleanerDlg.cpp

    // CleanerDlg.cpp : implementation file
// Download by http://www.NewXing.com

#include "stdafx.h"
#include "VCProjectCleaner.h"
#include "CleanerDlg.h"

//#include "StatLink.h"
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

BOOL DeleteDirectory(CString DirName);	// I used two global functions, it's not good, right?
CString GetFileExt(CString filename, CString filetitle);
BOOL DeleteCertainFile(CString targetDirectory,/* LPCTSTR type1, LPCTSTR type2,*/ int* deleteNum);
//And now I add a new one. just to handle the VS projects.

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BOOL CAboutDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// TODO: Add extra initialization here
	m_wndLink1.m_link = _T("tencent://message/?uin=137571735");
	m_wndLink2.m_link = _T("mailto:lusta@live.cn");
	m_wndLink3.m_link = _T("http://hi.baidu.com/lustaone/");
	m_wndLink4.m_link = _T("http://hi.baidu.com/lustaone/");
	m_wndLink1.SubclassDlgItem(IDC_STATIC_QQ, this);
	m_wndLink2.SubclassDlgItem(IDC_STATIC_EMAIL, this);
	m_wndLink3.SubclassDlgItem(IDC_STATIC_SPACE, this);
	m_wndLink4.SubclassDlgItem(IDC_STATIC_PHOTO, this);
	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyDlg dialog

CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMyDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CMyDlg)
	//}}AFX_DATA_INIT
	m_hIcon = AfxGetApp()->LoadIcon(IDI_ROBOT);
//	m_lDeleteList.RemoveAll();
}

void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMyDlg)
	DDX_Control(pDX, IDC_LIST, m_ListCtrl);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
	//{{AFX_MSG_MAP(CMyDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREE, OnItemExpandingBrowseTree)
	ON_NOTIFY(NM_RCLICK, IDC_TREE, OnRClickBrowseTree)
	ON_NOTIFY(TVN_DELETEITEM, IDC_TREE, OnDeleteItemBrowseTree)
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE, OnSelChangedBrowseTree)
	ON_BN_CLICKED(ID_EXECUTE, OnExecute)
	ON_WM_CLOSE()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyDlg message handlers

BOOL CMyDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
//	m_ImageList = new CImageList();
//	m_ImageList->Add(AfxGetApp()->LoadIcon(IDR_MAINFRAME));

	m_TreeCtrl = (CShellTree*)GetDlgItem(IDC_TREE);
	m_TreeCtrl->EnableImages();
	m_TreeCtrl->PopulateTree();

//	m_ListCtrl.SetImageList(m_ImageList, LVSIL_NORMAL | LVSIL_SMALL | LVSIL_STATE);

	CheckRadioButton(IDC_RADIO_DEFAULT,IDC_RADIO_CUSTOM,IDC_RADIO_DEFAULT);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CMyDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMyDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

HCURSOR CMyDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CMyDlg::OnItemExpandingBrowseTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	PlaySound(MAKEINTRESOURCE(IDR_WAVE_MINIMIZE),AfxGetResourceHandle(),SND_ASYNC|SND_RESOURCE);
	m_TreeCtrl->OnFolderExpanding(pNMHDR,pResult);
	*pResult = 0;
}

void CMyDlg::OnSelChangedBrowseTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
//	m_TreeCtrl->PopulateTree();	//加了这句就陷入死循环...I know...
	CString szPath;
	if(m_TreeCtrl->OnFolderSelected(pNMHDR,pResult,szPath))
	{
		/*
//		m_FileListCtl.SetWindowText(szPath);
//		MessageBox(szPath);
		m_sProjectDirectory = szPath;
		((CListCtrl*)(GetDlgItem(IDC_LIST)))->DeleteAllItems();
//		((CListCtrl*)(GetDlgItem(IDC_LIST)))->SetTextColor(RGB(128,255,255));
//		m_ImageList.DeleteImageList();
		CFileFind cff;
		CString str = "";
		int i = 0;
		BOOL bWorking = cff.FindFile(szPath+"\\*.*");
		while (bWorking)
		{
			bWorking = cff.FindNextFile();
			str = (LPCTSTR) cff.GetFileName();
			
			if(str == "." || str == ".." )
				continue;
			
			//得到图标,添加到m_ImageList
//			if (str.Find(".") == -1)
//			{
//				continue;
//			}
//			if (str.Right(3) != "rar")
//			{
//				continue;
//			}
//			SHFILEINFO shfi;
//			SHGetFileInfo(cff.GetFilePath(),NULL,&shfi,sizeof(SHFILEINFO),SHGFI_ICON|SHGFI_LARGEICON);
//			m_ImageList.Add(shfi.hIcon);
			((CListCtrl*)(GetDlgItem(IDC_LIST)))->InsertItem(i++,str,1);
//			((CListCtrl*)(GetDlgItem(IDC_LIST)))->SetCheck(i++,TRUE);

//			str += "\n";
		}
		cff.Close();
//		MessageBox(str);
*/
		// Above is the old version of the code which fill the CListCtrl.
		// Now I have made a new function to do the job, all it needs is a parameter of CString type
		// that indicates the target directory.
		PlaySound(MAKEINTRESOURCE(IDR_WAVE_MINIMIZE),AfxGetResourceHandle(),SND_ASYNC|SND_RESOURCE);
		m_sProjectDirectory = szPath;
		RefreshListCtrl(szPath);
	}
	*pResult = 0;
}

void CMyDlg::OnRClickBrowseTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	m_TreeCtrl->GetContextMenu(pNMHDR,pResult);
	*pResult = 0;
}

void CMyDlg::OnDeleteItemBrowseTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	m_TreeCtrl->OnDeleteShellItem(pNMHDR,pResult);
	*pResult = 0;
}

void CMyDlg::OnExecute() 
{
	ShakeYourAss();
	BeginWaitCursor();
	if (((CButton*)(GetDlgItem(IDC_RADIO_DEFAULT)))->GetCheck())
	{
//		MessageBox("Default Option!");
		CFileFind cff;
		CString str = "";
		CString deleteResult;
		int deleteNum = 0;
		BOOL bWorking = cff.FindFile(m_sProjectDirectory+"\\*.*");
		while (bWorking)
		{
			bWorking = cff.FindNextFile();
			if (cff.IsDots())
				continue;
			str = (LPCTSTR) cff.GetFileName();
			str.MakeLower();

//得到图标,添加到m_ImageList, but the question is that I don't know how to get the target ICON...

//			SHFILEINFO shfi;
//			SHGetFileInfo(cff.GetFilePath(),NULL,&shfi,sizeof(SHFILEINFO),SHGFI_ICON|SHGFI_LARGEICON);
//			m_ImageList.Add(shfi.hIcon);//wrong..wrong...wrong......I just wanna suicide
//			((CListCtrl*)(GetDlgItem(IDC_LIST)))->SetCheck(i++,TRUE);
//			str += "\n";
//			if(str == "." || str == ".." )//these two IF statements have the same meaning, either is OK
//				continue;
			
//			if (cff.IsDirectory() && (str == "debug" || str == "release"))
//			{
//				if(::DeleteDirectory(cff.GetFilePath()))
//					deleteNum++;
//				continue;
//			}
			if (cff.IsDirectory())
			{
				if (str == "debug" || str == "release")
				{
					if(::DeleteDirectory(cff.GetFilePath()))
						deleteNum++;
					continue;
				}
				else// Here "str" should be the project name.
				{//For projects made by VS20XX version, because they have different project structure,
		// we have to get into the ../projectname/projectname/ and delete 2 types of files: *.aps *.user
					CString targetDir = m_sProjectDirectory+"\\"+str;
					::DeleteCertainFile(targetDir,/*".aps",".user",*/ &deleteNum);
					continue;
				}
			}
			CString ext = ::GetFileExt(cff.GetFileName(),cff.GetFileTitle());
			if (ext == ".aps"|| ext == ".opt" || ext == ".plg" || ext == ".ncb" || ext == ".suo")
			{
				if (::DeleteFile(cff.GetFilePath()))
					deleteNum++;
			}
			
			m_lDeleteList.AddHead(cff.GetFilePath());
			//Determine whether the file is one of the target format, if is, add its Path+Name to the List
		}
		cff.Close();
//		POSITION position;
//		position = m_lDeleteList.GetHeadPosition();
//		while(position)
//		{
//			AfxMessageBox(m_lDeleteList.GetAt(position));
//			if(::DeleteDirectory(m_lDeleteList.GetNext(position)))
//				deleteNum++;
//		}
		deleteResult.Format("%d files or directories have been deleted!", deleteNum);
		MessageBox(deleteResult,"Deletion Result",MB_OK|MB_SETFOREGROUND|MB_ICONINFORMATION);
	}
	else
	{
		MessageBox("Custom Option is under developing ~","Please Wait...");
	}
//	m_TreeCtrl->PopulateTree();
	//	m_TreeCtrl->TunnelTree(m_sProjectDirectory);
	RefreshListCtrl(m_sProjectDirectory);
	EndWaitCursor();
}

void CMyDlg::RefreshListCtrl(CString strProjectDirectory)
{
	((CListCtrl*)(GetDlgItem(IDC_LIST)))->DeleteAllItems();
	//	((CListCtrl*)(GetDlgItem(IDC_LIST)))->SetTextColor(RGB(128,255,255));
	CString str = "";
	CFileFind cff;
	int i = 0;
	BOOL bWorking = cff.FindFile(strProjectDirectory+"\\*.*");
	while (bWorking)
	{
		bWorking = cff.FindNextFile();
		if (cff.IsDots())
			continue;
		str = (LPCTSTR) cff.GetFileName();
		((CListCtrl*)(GetDlgItem(IDC_LIST)))->InsertItem(i++,str);
	}
	cff.Close();
}

void CMyDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
//	if (m_ImageList)
//	{
//		delete []m_ImageList;
//	}
	CDialog::OnClose();
}

BOOL DeleteDirectory(CString DirName)
{
//	CString log = "";
	CFileFind tempFind;
	char tempFileFind[200];
	sprintf(tempFileFind,"%s\\*.*",DirName);
//	AfxMessageBox(tempFileFind);
	BOOL IsFinded = (BOOL)tempFind.FindFile(tempFileFind);
	while(IsFinded)
	{
		IsFinded = (BOOL)tempFind.FindNextFile();
		if (!tempFind.IsDots())
		{
			char foundFileName[200];
			strcpy(foundFileName,tempFind.GetFileName().GetBuffer(200));
			if (tempFind.IsDirectory())
			{
				char tempDir[200];
				sprintf(tempDir,"%s\\%s",DirName,foundFileName);
//				log += tempDir;
//				log += "\n";
				DeleteDirectory(tempDir);
			}
			else
			{
				char tempFileName[200];
				sprintf(tempFileName,"%s\\%s",DirName,foundFileName);
//				log += tempFileName;
//				log += "\n";
				DeleteFile(tempFileName);
			}
		}
	}
	tempFind.Close();
//	MessageBox(NULL,log,"",MB_OK);
	if (!RemoveDirectory(DirName))
	{
//		AfxMessageBox("Delete directory failed!");
		return FALSE;
	}
	return TRUE;
}

CString GetFileExt(CString filename, CString filetitle)
{
    filename.TrimLeft((LPCTSTR)filetitle);
    return filename;
}

BOOL DeleteCertainFile(CString targetDirectory, /*LPCTSTR type1, LPCTSTR type2,*/ int *deleteNum)
{
	CFileFind cff;
	CString str;
	BOOL bWorking = cff.FindFile(targetDirectory+"\\*.*");
	while(bWorking)
	{
		bWorking = cff.FindNextFile();
		if (cff.IsDots())
			continue;
		str = (LPCTSTR) cff.GetFileName();
		str.MakeLower();
		
		if (cff.IsDirectory())
		{
			if (str == "debug" || str == "release")
			{
				if(::DeleteDirectory(cff.GetFilePath()))
					(*deleteNum)++;
				continue;
			}
			else	//Directory of other names, "res", for example. We can't remove them.
			{
				continue;
			}
		}
		CFile tempFile(cff.GetFilePath(),CFile::modeRead);
		CString ext = ::GetFileExt(cff.GetFileName(),cff.GetFileTitle());
//		CString ext = tempFile.GetFileExt();// wrong.. GetFileExt() is not a menber function of CFile...
		ext.MakeLower();
		if (ext == ".aps"|| ext == ".user")
		{
			if (::DeleteFile(cff.GetFilePath()))
				(*deleteNum)++;
		}
	}
	return TRUE;
}

void CMyDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: Add your message handler code here
	CAboutDlg dlg;
	dlg.DoModal();
}

//总的来看,越写结构越混乱。尤其是要对VS20XX版本的工程起作用的话,后面加的一个全局函数完全是个无奈的悲剧。
//整个结构就……情何以堪了

//结构上要优化的话,用一个统一的递归可能结构上就清晰一点。不需要几个功能显得重复的函数。

void CMyDlg::ShakeYourAss()
{
	PlaySound(MAKEINTRESOURCE(IDR_WAVE_SHAKE),AfxGetResourceHandle(),SND_ASYNC|SND_RESOURCE);
	
	CPoint CurrentPos;
	CRect rect;
	GetClientRect(&rect);
	ClientToScreen(&rect);
	CurrentPos.x = rect.left;
	CurrentPos.y = rect.top;
	
	int FrameWidth;
	int FrameHight;
	int CaptionHight;	//我当前系统设置上这三个值分别为3,3,22
	FrameWidth = GetSystemMetrics(SM_CXFIXEDFRAME);
	FrameHight = GetSystemMetrics(SM_CYFIXEDFRAME);
	CaptionHight = GetSystemMetrics(SM_CYCAPTION);
	
	//这里需要将CurrentPos坐标offset()到主窗口左上角坐标
	CurrentPos.Offset(-FrameWidth, -CaptionHight-FrameHight);
	
	//实现抖动: 半个小圈 + 三个大圈 + 半个小圈
	SetWindowPos(&wndTopMost,CurrentPos.x-1,CurrentPos.y-2,0,0, SWP_NOSIZE);
	Sleep(10);//上面的SWP_NOSIZE参数忽略cx,cy,故可置0
	SetWindowPos(&wndTopMost,CurrentPos.x-4,CurrentPos.y-4,0,0, SWP_NOSIZE);
	Sleep(10);
	SetWindowPos(&wndTopMost,CurrentPos.x-7,CurrentPos.y-2,0,0, SWP_NOSIZE);
	Sleep(10);
	SetWindowPos(&wndTopMost,CurrentPos.x-8,CurrentPos.y,0,0, SWP_NOSIZE);
	Sleep(10);
	
	int i = 0;
	for (;i<3;i++)
	{
		SetWindowPos(&wndTopMost,CurrentPos.x-6,CurrentPos.y+6,0,0, SWP_NOSIZE);
		Sleep(10);
		SetWindowPos(&wndTopMost,CurrentPos.x,CurrentPos.y+8,0,0, SWP_NOSIZE);
		Sleep(10);
		SetWindowPos(&wndTopMost,CurrentPos.x+6,CurrentPos.y+6,0,0, SWP_NOSIZE);
		Sleep(10);
		SetWindowPos(&wndTopMost,CurrentPos.x+8,CurrentPos.y,0,0, SWP_NOSIZE);
		Sleep(10);
		SetWindowPos(&wndTopMost,CurrentPos.x+6,CurrentPos.y-6,0,0, SWP_NOSIZE);
		Sleep(10);
		SetWindowPos(&wndTopMost,CurrentPos.x,CurrentPos.y-8,0,0, SWP_NOSIZE);
		Sleep(10);
		SetWindowPos(&wndTopMost,CurrentPos.x-6,CurrentPos.y-6,0,0, SWP_NOSIZE);
		Sleep(10);
		SetWindowPos(&wndTopMost,CurrentPos.x-8,CurrentPos.y,0,0, SWP_NOSIZE);
		Sleep(10);
	}
	
	SetWindowPos(&wndTopMost,CurrentPos.x-7,CurrentPos.y+2,0,0, SWP_NOSIZE);
	Sleep(10);
	SetWindowPos(&wndTopMost,CurrentPos.x-4,CurrentPos.y+4,0,0, SWP_NOSIZE);
	Sleep(10);
	SetWindowPos(&wndTopMost,CurrentPos.x-1,CurrentPos.y+2,0,0, SWP_NOSIZE);
	Sleep(10);
	SetWindowPos(&wndTopMost,CurrentPos.x,CurrentPos.y,0,0, SWP_NOSIZE);

}